[runtime/simplex]]: add phantom order support for passive price and liquidity indexing#983
[runtime/simplex]]: add phantom order support for passive price and liquidity indexing#983dharjeezy wants to merge 12 commits into
Conversation
| /// registered phantom order. Called by the intent coprocessor service. | ||
| #[pallet::call_index(7)] | ||
| #[pallet::weight(T::WeightInfo::register_phantom_order())] | ||
| pub fn register_phantom_order( |
There was a problem hiding this comment.
This is not correct, the phantom order should be generated by the runtime in the pallet hooks
|
|
||
| Ok(()) | ||
| } | ||
|
|
There was a problem hiding this comment.
There's no extrinsic to setup the phantom order details, like token pairs, chain for the order?
| * one reverts, and `null` when the simulation could not be run (e.g. RPC error, | ||
| * unsupported node). | ||
| */ | ||
| async function simulateTokenTransfers( |
There was a problem hiding this comment.
This is not correct, simulate the bid as is, don't change the solver's balance, only state override needed is the block number so the order is not expired when simulating
| chain: &[u8], | ||
| pair: &PhantomTokenPair, | ||
| ) -> H256 { | ||
| let mut preimage = Vec::new(); |
There was a problem hiding this comment.
The phantom order should be an actual intent gateway order.
…ent phantom order price snapshot indexing handlers
| beneficiary: FixedBytes::from([0u8; 32]), | ||
| assets: vec![sol_types::TokenInfo { | ||
| token: FixedBytes::from(token_b_bytes), | ||
| amount: AlloyU256::from(min_output), |
|
|
||
| parameter_types! { | ||
| pub const IntentsStorageDepositFee: Balance = EXISTENTIAL_DEPOSIT * 10; | ||
| pub const IntentsPhantomOrderBidWindow: u32 = 15; |
| params: [ | ||
| { from: solver, to: solver, data: callData }, | ||
| "latest", | ||
| { [gatewayAddress]: { code: "0x" } }, |
There was a problem hiding this comment.
This is wrong, the bid should be validated against intent gatway's code.
the override required is inserting the phantom order commitment into the intent gateway's contract state
| if (!simOk) continue | ||
|
|
||
| const tokenAddress = bytes32ToBytes20(output.token) | ||
| const balance = await getTokenBalance(evmUrl, tokenAddress, solver) |
There was a problem hiding this comment.
You need to fetch the filler's balance from the Aave's USDC/USDT vault and cngn yield vault also
|
|
||
| const tokenAddress = bytes32ToBytes20(output.token) | ||
| const balance = await getTokenBalance(evmUrl, tokenAddress, solver) | ||
| if (balance === null || balance < outputAmount) continue |
There was a problem hiding this comment.
Why are we not storing the LP's balance?
|
|
||
| const tokenAddress = bytes32ToBytes20(output.token) | ||
| const balance = await getTokenBalance(evmUrl, tokenAddress, solver) | ||
| if (balance === null || balance < outputAmount) continue |
There was a problem hiding this comment.
This check is not necessary, if the simulation succeeded the filler must have some balance somewhere
| if (balance === null || balance < outputAmount) continue |
… and gateway state override for phantom order simulation
|
|
||
| // Use pallet-ismp's time provider so the deadline is a real chain timestamp | ||
| // (non-zero). Simulation uses block 0 (timestamp=0) so the check still passes. | ||
| let deadline_secs = <T as pallet_ismp::Config>::TimestampProvider::now().as_secs(); |
There was a problem hiding this comment.
Deadline is in blocks, I meant fetch the latest state machine height for the order chain and use that as the deadline
| token_a: pair.token_a, | ||
| token_b: pair.token_b, | ||
| standard_amount: pair.standard_amount, | ||
| min_output: pair.min_output, |
There was a problem hiding this comment.
Remove this min_output config, it's not useful
| commitment: string, | ||
| ): Promise<boolean> { | ||
| try { | ||
| const { slot1, slot2 } = requestCommitmentKey(commitment as HexString) |
There was a problem hiding this comment.
Why are you using request commitment keys?
You are meant to override this storage in IntentGateway contract, please check how the contract works
mapping(bytes32 => mapping(address => uint256)) public _orders;
| jsonrpc: "2.0", | ||
| method: "eth_call", | ||
| params: [ | ||
| { from: solver, to: solver, data: callData }, |
There was a problem hiding this comment.
This is not correct, is the to no meant to be the intent gateway contract?
|
|
||
| const output = fillData.outputs[0] | ||
| const tokenAddress = bytes32ToBytes20(output.token) | ||
| const totalBalance = await getTotalSolverBalance(evmUrl, phantom.chain, tokenAddress, solver) |
There was a problem hiding this comment.
Get solver balance across all configured evm chains
| const totalBalance = await getTotalSolverBalance(evmUrl, phantom.chain, tokenAddress, solver) | ||
|
|
||
| prices.push(output.amount) | ||
| if (totalBalance > bestLpBalance) bestLpBalance = totalBalance |
There was a problem hiding this comment.
This is wrong, store the balance of each Lp that submitted a valid bid independently, also balances should be stored by token
| // ERC-4626 vault addresses per chain, keyed by underlying token address (lowercase). | ||
| // Aave stata token addresses sourced from https://github.com/bgd-labs/aave-address-book | ||
| // Values are arrays because multiple vaults may wrap the same underlying token. | ||
| export const YIELD_VAULT_ADDRESSES: Record<string, Record<string, string[]>> = { |
There was a problem hiding this comment.
Add this to the builld pipeline like other addresses, don't harcode it here
| }, | ||
| // Optimism | ||
| "EVM-10": { | ||
| // USDC.e (bridged) → stataUSDC.e |
| deadline: 0n, | ||
| nonce: BigInt(event.createdAt), | ||
| fees: 0n, | ||
| session: ZERO_ADDRESS, |
There was a problem hiding this comment.
This session address is not correct
| // Reconstruct the Order with the same field values the pallet used when computing the commitment. | ||
| const ZERO_BYTES32 = `0x${"00".repeat(32)}` as HexString | ||
| const ZERO_ADDRESS = `0x${"00".repeat(20)}` as HexString | ||
| const phantomOrder: Order = { |
There was a problem hiding this comment.
This order is wrong, fetch it from offchain storage
Adds phantom order price and liquidity indexing to the intent coprocessor. The pallet gains two new extrinsics — register_phantom_order (permissionless) and set_phantom_bid_window (governance) — along with the CurrentPhantomOrder and PhantomBidWindow storage items and a phantom_bid_window() helper that mirrors the existing storage_deposit_fee() fallback pattern.
The SubQuery indexer is extended with
handlePhantomOrderRegisteredandhandlePhantomBidPlacedhandlers that decode each filler's user operation, extract proposed output amounts, and run a lightweight ERC-20 transfer simulation via state overrides to produce a simulationSuccess signal indexed alongside each bid.closes #977